package com.thssh.ui.lsn05.view;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.thssh.ui.R;

/**
 * 效果和谷歌提供额不太一样。网上说在画bitmap时才是谷歌的效果。
 * 博客：http://blog.csdn.net/wingichoy/article/details/50534175
 * bitmap效果：com.thssh.ui.lsn05.view.BitmapXfermodeView
 *
 * @author zhangyugehu
 * @version V1.0
 * @date 2017/09/14
 * email: zhangyugehu@163.com
 */

public class XfermodeView extends View {

    private static final int DEF_WIDTH = 200;
    private int mMode;

//    private Paint mDstCiclePaint;
    private Paint mXferModePaint;
    private Paint mTextPaint;
    private int padding = 20;
    private int textHeight = 50;
    private String mModeName;
    private PorterDuff.Mode xMode;

    private AlertDialog mTipDialog;

    private int mWidth;
    private int mHeight;

    public XfermodeView(Context context) {
        this(context, null);
    }

    public XfermodeView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XfermodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        mXferModePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(Color.BLACK);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setTextSize(30);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.XfermodeView);
        mMode = typedArray.getInt(R.styleable.XfermodeView_mode, 0);
        mTipDialog = new AlertDialog.Builder(getContext())
                .setTitle("模式详情")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .create();
        xMode = getXfermodeMode();
        typedArray.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if(widthMode == MeasureSpec.EXACTLY){
            mWidth = MeasureSpec.getSize(widthMeasureSpec);
            mHeight = mWidth;
        }else{
            mWidth = DEF_WIDTH;
            mHeight = DEF_WIDTH;
        }
        setMeasuredDimension(mWidth, mHeight);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int saveLayer = canvas.saveLayer(0, 0, mWidth, mHeight, null, Canvas.ALL_SAVE_FLAG);
        drawDstCircle(canvas);
        if(xMode != null) {
            mXferModePaint.setXfermode(new PorterDuffXfermode(xMode));
        }
        drawSrcRect(canvas);
        drawText(canvas, mModeName);

        mXferModePaint.setXfermode(null);
        canvas.restoreToCount(saveLayer);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                showTip();
                break;
        }
        return super.onTouchEvent(event);
    }

    private String getString(int id){
        return getContext().getResources().getString(id);
    }

    private void showTip() {
        String message = "DST：圆形\n" +
                "SRC：矩形\n\n";
        switch (mMode){
            case 0:
                message += "[0, 0]";
                break;
            case 1:
                message += getString(R.string.des_xformode_src);
                break;
            case 2:
                message += "[Da, Dc]";
                break;
            case 3:
                message += "[Sa + (1 - Sa)*Da, Rc += Sc + (1 - Sa)*Dc]";
                break;
            case 4:
                message += "[Sa + (1 - Sa)*Da, Rc += Dc + (1 - Da)*Sc]";
                break;
            case 5:
                message += getString(R.string.des_xformode_src_in);
                break;
            case 6:
                message += "[Sa * Da, Sa * Dc]";
                break;
            case 7:
                message += "[Sa * (1 - Da), Sc * (1 - Da)]";
                break;
            case 8:
                message += "[Da * (1 - Sa), Dc * (1 - Sa)]";
                break;
            case 9:
                message += "[Da, Sc * Da + (1 - Sa) * Dc]";
                break;
            case 10:
                message += "[Sa, Sa * Dc + Sc * (1 - Da)]";
                break;
            case 11:
                message += "[Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]";
                break;
            case 12:
                message += "Saturate(S + D)";
                break;
            case 13:
                message += "[Sa * Da, Sc * Dc]";
                break;
            case 14:
                message += "[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]";
                break;
            case 15:
                message += "Saturate(S + D)";
                break;
            case 16:
                message += "[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]";
                break;
            case 17:
                message += "[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]";
                break;
            default:
                return;
        }
        showTipDialog(message);
    }

    private PorterDuff.Mode getXfermodeMode() {
        PorterDuff.Mode xMode = PorterDuff.Mode.CLEAR;
        mModeName = "CLEAR[0, 0]";
        switch (mMode){
            case 0:
                xMode = PorterDuff.Mode.CLEAR;
                mModeName = "CLEAR";
                break;
            case 1:
                xMode = PorterDuff.Mode.SRC;
                mModeName = "SRC";
                break;
            case 2:
                xMode = PorterDuff.Mode.DST;
                mModeName = "DST";
                break;
            case 3:
                xMode = PorterDuff.Mode.SRC_OVER;
                mModeName = "SRC_OVER";
                break;
            case 4:
                xMode = PorterDuff.Mode.DST_OVER;
                mModeName = "DST_OVER";
                break;
            case 5:
                xMode = PorterDuff.Mode.SRC_IN;
                mModeName = "SRC_IN";
                break;
            case 6:
                xMode = PorterDuff.Mode.DST_IN;
                mModeName = "DST_IN";
                break;
            case 7:
                xMode = PorterDuff.Mode.SRC_OUT;
                mModeName = "SRC_OUT";
                break;
            case 8:
                xMode = PorterDuff.Mode.DST_OUT;
                mModeName = "DST_OUT";
                break;
            case 9:
                xMode = PorterDuff.Mode.SRC_ATOP;
                mModeName = "SRC_ATOP";
                break;
            case 10:
                xMode = PorterDuff.Mode.DST_ATOP;
                mModeName = "DST_ATOP";
                break;
            case 11:
                xMode = PorterDuff.Mode.XOR;
                mModeName = "XOR";
                break;
            case 12:
                xMode = PorterDuff.Mode.ADD;
                mModeName = "ADD";
                break;
            case 13:
                xMode = PorterDuff.Mode.MULTIPLY;
                mModeName = "MULTIPLY";
                break;
            case 14:
                xMode = PorterDuff.Mode.SCREEN;
                mModeName = "SCREEN";
                break;
            case 15:
                xMode = PorterDuff.Mode.OVERLAY;
                mModeName = "OVERLAY";
                break;
            case 16:
                xMode = PorterDuff.Mode.DARKEN;
                mModeName = "DARKEN";
                break;
            case 17:
                xMode = PorterDuff.Mode.LIGHTEN;
                mModeName = "LIGHTEN";
                break;
            default:
                xMode = null;
                mModeName = "NONE";
                break;
        }
        return xMode;
    }

    private void showTipDialog(String message) {
        mTipDialog.setTitle(mModeName + " 模式");
        mTipDialog.setMessage(message);
        mTipDialog.show();
    }

    private void drawText(Canvas canvas, String text) {
        canvas.drawText(text , mWidth / 2, mHeight - padding, mTextPaint);
    }

    private void drawSrcRect(Canvas canvas) {
        mXferModePaint.setColor(Color.GREEN);
        canvas.drawRect(mWidth * 1 / 3,
                mHeight * 1 / 3,
                mWidth - textHeight,
                mHeight - textHeight,
                mXferModePaint);
    }

    private void drawDstCircle(Canvas canvas) {
        mXferModePaint.setColor(Color.RED);
        canvas.drawCircle(mWidth * 1 / 3,
                mHeight * 1 / 3,
                (mHeight * 1 / 3) - padding,
                mXferModePaint);
    }
}
